package com.lgCore.client.workHandler.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lgCore.client.NettyClientBootstrap;
import com.lgCore.client.workHandler.ClientNettyBootStrapPool;
import com.lgCore.client.workHandler.ClientRpcData;
import com.lgCore.client.workHandler.ICommonRpcClientService;
import com.lgCore.common.ClientSession;
import com.lgCore.common.RpcBaseCommonEntity;
import com.lgCore.common.RpcException;
import com.lgCore.consumer.model.ClientZkData;
import com.lgCore.protoModel.ProtoMsg;
import com.lgCore.queue.ClientResultQueue;
import com.lgCore.util.ByteObjUtil;
import com.lgCore.util.IpAddr;
import com.lgCore.util.ProtoByteUtil;
import com.lgCore.util.StringUtils;
import io.netty.util.Attribute;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class CommonRpcClientServiceImpl implements ICommonRpcClientService {

    private static final Logger LOGGER = LoggerFactory.getLogger(CommonRpcClientServiceImpl.class);

    @Override
    public Object executeSendRequest(NettyClientBootstrap clientBootstrap, ProtoMsg.Message message) throws Exception {
        ProtoMsg.RpcRequest rpcRequest = message.getRpcRequest();
        //登录请求
        ProtoMsg.RpcRequest.Builder newRpcRequest = ProtoMsg.RpcRequest.newBuilder();
        newRpcRequest.setServiceName(rpcRequest.getServiceName());
        newRpcRequest.setMethodName(rpcRequest.getMethodName());
        newRpcRequest.setRequestObjects(rpcRequest.getRequestObjects());
        newRpcRequest.setRequestId(UUID.randomUUID().toString());
        newRpcRequest.setType(ProtoMsg.HeadType.RPC_REQUEST);
        newRpcRequest.setArgTypes(rpcRequest.getArgTypes());

        //记录到队列
        LinkedBlockingQueue<Object> responseQueue = new LinkedBlockingQueue<Object>(1);
//        try {
        //加入queue队列缓存
        ClientResultQueue.putResponse(newRpcRequest.getRequestId(), responseQueue);
        //发送消息
        Attribute<ClientSession> constantsAttributeKey = clientBootstrap.getChannel().attr(ClientSession.SESSION_KEY);

        ClientSession clientSession = constantsAttributeKey.get();
        if (clientSession != null) {
            newRpcRequest.setClientId(clientSession.getClientId());
        }
        //发送给netty服务端
        ProtoMsg.Message.Builder sendMessage = ProtoMsg.Message.newBuilder();
        sendMessage.setRpcRequest(newRpcRequest);
//        LOGGER.info("invok askMsg is"+ JSON.toJSONString(askMsg));
        clientBootstrap.getChannel().writeAndFlush(ProtoByteUtil.protoToByte(sendMessage));
        //查询队列结果
        Object result = responseQueue.poll(
                RpcBaseCommonEntity.maxMQTime,
                TimeUnit.SECONDS);


        if (null == result || !(result instanceof ProtoMsg.RpcResponse)) {
            throw new RpcException("rpc 调用接口报错");
        }

        ProtoMsg.RpcResponse rpcResponse = (ProtoMsg.RpcResponse) result;
        //取得请求类型
        if (!rpcResponse.getType().equals(ProtoMsg.HeadType.RPC_RESPONSE)) {
            throw new RpcException("rpc 返回类型不正确");
        }
        if (!rpcResponse.getIsSucess()) {
            throw new RpcException("接口调用错误:" + rpcResponse.getException());
        }
        ClientResultQueue.removeResponse(rpcResponse.getRequestId());
//        Object object= JSONObject.parse(rpcResponse.getResponse());
//        Object object= JSONObject.parse(rpcResponse.getResponse());
        Object object = ByteObjUtil.bytesToObject(rpcResponse.getResponse().toByteArray());

        return object;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    public NettyClientBootstrap getServerBootStrap(String serverAddr) {
        NettyClientBootstrap nettyClientBootstrap = ClientNettyBootStrapPool.getChannelByIpAddr(serverAddr);
        return nettyClientBootstrap;
    }

    public String getServerDataByZk(String serverName) {
        List<String> serverNodeList = ClientZkData.getDataByPath(serverName);

        if(serverNodeList==null || serverNodeList.isEmpty()){
            return null;
        }
        //如果是local，则查找本地IP一致的节点
        if ("local".equals(ClientRpcData.getProfilesActive().toLowerCase())) {
            serverNodeList = findLoadNode(serverNodeList);
        }
        //轮训
        String value = ClientZkData.getValueByTrain(serverNodeList);
        if (!StringUtils.isNullOrEmpty(value)) {
            //去除zk标识
            String[] strs = value.split(":");
            return strs[0] + ":" + strs[1];
        }
        return value;
    }

    /**
     * 当为local本地环境时，取跟自己IP一样的服务节点
     * 注：为local时，响应会慢，是因为需要实时获取本地IP
     *
     * @param serverNodeList
     * @author ligang
     * @date 2020/10/22
     */
    private List<String> findLoadNode(List<String> serverNodeList) {
        List<String> result = new ArrayList<>();
//      String localIp = IpAddr.getLinuxLocalIp();
        String localIp = ClientRpcData.getLocalIp();
        if (StringUtils.isNullOrEmpty(localIp)) {
            return serverNodeList;
        }
        for (String s : serverNodeList) {
            if (s.split(":")[0].equals(localIp)) {
                result.add(s);
            }
        }
        if (result.size() == 0) {
            //没有本地节点，原路返回
            return serverNodeList;
        }
        return result;
    }

    public void removeServerBootStrap(String serverAddr) {
        ClientNettyBootStrapPool.delKey(serverAddr);
    }
}
